﻿using System;
using System.Collections.Generic;
using System.Globalization;

namespace CodedUITestExtensions.Tree
{
    /// <summary>
    /// Tree node.
    /// </summary>
    public class TreeNode : IEquatable<TreeNode>
    {
        /// <summary>
        /// Gets tree node children.
        /// </summary>
        public TreeNodeList Children { get; private set; }

        /// <summary>
        /// Gets tree node value.
        /// </summary>
        public string Value { get; set; }

        /// <summary>
        /// Gets tree node parent.
        /// </summary>
        public TreeNode Parent { get; set; }

        /// <summary>
        /// Initializes a new instance of the <see cref="T:CodedUITestExtensions.Tree.TreeNode"/> class.
        /// </summary>
        /// <param name="value">Tree node value.</param>
        public TreeNode(string value)
        {
            Parent = null;
            Value = value;
            Children = new TreeNodeList(this);
        }

        /// <summary>
        /// Initializes a new instance of the <see cref="T:CodedUITestExtensions.Tree.TreeNode"/> class.
        /// </summary>
        /// <param name="value">Tree node value.</param>
        /// <param name="parent">Parent node for tree node.</param>
        public TreeNode (string value, TreeNode parent)
        {
            Parent = parent;
            Value = value;
            Children = new TreeNodeList(this);
        }

        /// <summary>
        /// Equals.
        /// </summary>
        /// <param name="other">TreeNode.</param>
        /// <returns>Result.</returns>
        public bool Equals(TreeNode other)
        {
            if (other == null)
            {
                return false;
            }

            if (!Value.Equals(other.Value))
            {
                return false;
            }

            int count = Children.Count;
            if (count != other.Children.Count)
            {
                return false;
            }

            for (int i = 0; i < count; ++i)
            {
                if (!Children[i].Equals(other.Children[i]))
                {
                    return false;
                }
            }

            return true;
        }

        /// <summary>
        /// Equals.
        /// </summary>
        /// <param name="obj">OrganizationTree.</param>
        /// <returns>Result.</returns>
        public override bool Equals(Object obj)
        {
            return Equals(obj as TreeNode);
        }

        /// <summary>
        /// GetHashCode.
        /// </summary>
        /// <returns>Result.</returns>
        public override int GetHashCode()
        {
            return Children.GetHashCode() ^ Children.Count.GetHashCode();
        }

        /// <summary>
        /// Gets string representation of tree node.
        /// </summary>
        /// <returns>String representation.</returns>
        public override string ToString()
        {
            // Формируем полный путь к узлу.
            var nodePath = new List<string>();
            TreeNode node = this;
            while (node != null)
            {
                nodePath.Insert(0, node.Value);
                node = node.Parent;
            }

            return String.Format(CultureInfo.CurrentCulture,
                "Full path to tree node - «{0}»", string.Join("-", nodePath.ToArray()));
        } 
    }
}
